#include <QPainter>
#include <QSettings>
#include <QGuiApplication>
#include <QShortcut>
#include <QMouseEvent>
#include "Utils.hxx"
#include "VideoView.hxx"
#include "Sequence.hxx"
#include "FramePool.hxx"
#include "VideoThread.hxx"
#include "VideoController.hxx"
#include "TrackedObject.hxx"
#include "Project.hxx"
#include "MainWindow.hxx"
#include "Shape.hxx"


#define MIN_ZOOM_SCALE (0.1)
#define MAX_ZOOM_SCALE (8.0)

int cursorDist = 10;

VideoView::VideoView(QWidget *parent):QWidget(0)
{
	_mainWindow = 0;

    _imageData = 0;

	_timer = new QTimer();
    _timer->setInterval(5);
	
    connect(_timer,SIGNAL(timeout()),this,SLOT(updateFrame()));

	_timer->start();

	_dragingRect = false;

	_status = VW_STATUS_DISPLAYING;
	_prevStatus = VW_STATUS_DISPLAYING;

	_zoomScale = 1.0;
	_zoomAutoScale = 1.0;
	_zoomOffset = QPoint(0, 0);

	//QShortcut* shortcutKeyESC = new QShortcut(QKeySequence(Qt::Key_Escape), this);
	//connect(shortcutKeyESC, SIGNAL(activated()), this, SLOT(onKeyEscape()));

	//QShortcut* shortcutKeyT = new QShortcut(QKeySequence(Qt::Key_T), this);
	//connect(shortcutKeyT, SIGNAL(activated()), this, SLOT(prevFrame()));

	//QShortcut* shortcutKeyScale = new QShortcut(QKeySequence(Qt::Key_S), this);
	//connect(shortcutKeyScale, SIGNAL(activated()), this, SLOT(zoomFit()));

	//QShortcut* shortcutKeyScaleUp = new QShortcut(QKeySequence(Qt::Key_PageUp), this);
	//connect(shortcutKeyScaleUp, SIGNAL(activated()), this, SLOT(zoomIn()));

	//QShortcut* shortcutKeyScaleDown = new QShortcut(QKeySequence(Qt::Key_PageDown), this);
	//connect(shortcutKeyScaleDown, SIGNAL(activated()), this, SLOT(zoomOut()));

	setMouseTracking(true);
	setMinimumHeight(400);
	setMinimumWidth(600);

	//setFocus();
}

void VideoView::paintEvent(QPaintEvent *event)
{
	if (!_imageData)
		return;

	Sequence* sequence = _project->getActiveSequence();

	if (!sequence) return;

    QImage image(_imageData + sizeof(VideoFrameInfo), sequence->getVideoWidth(), sequence->getVideoHeight(),QImage::Format_RGB888);

	//QRect rect = QRect(0, 0, geometry().width(), geometry().height());

	//int canvasWidth = geometry().width();
	//int canvasHeight = geometry().height();

	//int imageWidth = sequence->getVideoWidth();
	//int imageHeight = sequence->getVideoHeight();

	//float imageScale = imageWidth * 1.0 / imageHeight;
	//float canvasScale = canvasWidth * 1.0 / canvasHeight;

	//QRect targetRect = rect;

	//if (canvasScale / imageScale > 1.0)
	//{
	//	targetRect.setX((canvasWidth - canvasHeight * imageScale) / 2.0);
	//	targetRect.setY(0);
	//	targetRect.setWidth(canvasHeight * imageScale);
	//	targetRect.setHeight(canvasHeight);
	//}
	//else
	//{
	//	targetRect.setX(0);
	//	targetRect.setY((canvasHeight - canvasWidth / imageScale) / 2.0);
	//	targetRect.setWidth(canvasWidth);
	//	targetRect.setHeight(canvasWidth / imageScale);
	//}

	//_zoomAutoScale = targetRect.width() * 1.0 / imageWidth;

	//float totalScle = _zoomAutoScale * _zoomScale;

	//int twidth = imageWidth * totalScle;
	//int theight = imageHeight * totalScle;
	//int left = targetRect.left() + (targetRect.width() - twidth) / 2.0;
	//int top = targetRect.top() + (targetRect.height() - theight) / 2.0;

	//left += _zoomOffset.x();
	//top += _zoomOffset.y();

	//if (_status == ViewStatus::VW_STATUS_FRAME_DRAGING)
	//{
	//	left += _endPoint.x() - _startPoint.x();
	//	top += _endPoint.y() - _startPoint.y();
	//}

    QPainter painter(this);
	//painter.drawImage(rect, image.rgbSwapped(), QRect(0,0,image.width(),image.height()));
	painter.drawImage(getImageQRect(), image.rgbSwapped(), QRect(0, 0, image.width(), image.height()));

	drawNewObject(painter);

	drawTrackingObject(painter);

	drawTrackedObject(painter);

	drawTextInfo(painter);

    painter.end();
}

void VideoView::updateFrame()
{
	Sequence* sequence = _project->getActiveSequence();

	if (!sequence) return;

    if( !_imageData )
    {
        int imgWidth = sequence->getVideoWidth();
        int imgHeight = sequence->getVideoHeight();

        if( imgWidth < 1 || imgHeight < 1 )
            return;

		FramePool* pool = sequence->getFramePool();

        _imageData = (uchar*)malloc(pool->getPageSize());

        return;
    }
	
	FramePool* imagePool = 0;
	if (_controller->isTracking())
		imagePool = sequence->getTrackedFramePool();
	else
		imagePool = sequence->getFramePool();
	//if (sequence->getFramePool()->popFrame((char*)_imageData))
	//if (sequence->getTrackedFramePool()->popFrame((char*)_imageData))
	if( imagePool->popFrame((char*)_imageData))
	{
		VideoFrameInfo* vfi = (VideoFrameInfo*)_imageData;

		_frameIndex = vfi->FrameIndex;

		sequence->setCurrentFrameIndex(_frameIndex);

		sequence->setCurrentTimestamp(vfi->TimeStamp);

		update();

		emit frameInfoUpdated();
	}
}

void VideoView::mousePressEvent(QMouseEvent *event)
{
	if (event->buttons() & Qt::RightButton)
	{
		_startPoint = event->pos();
		_endPoint = _startPoint;
		_dragingRect = false;
		_prevStatus = _status;
		_status = ViewStatus::VW_STATUS_FRAME_DRAGING;
		setCursor(QCursor(Qt::SizeAllCursor));
	}

	if (_status == VW_STATUS_DISPLAYING)
	{
		if (event->buttons() & Qt::LeftButton)
		{
			_startPoint = event->pos();
			_endPoint = _startPoint;
			_dragingRect = true;
		}
	}
	else if (_status == VW_STATUS_EDITING)
	{
		Qt::CursorShape shape = cursor().shape();

		if (shape == Qt::SizeAllCursor)
		{
			_startPoint = event->pos();
			_endPoint = _startPoint;
		}
		else if (shape == Qt::SizeHorCursor)
		{
			_startPoint = event->pos();
			_endPoint = _startPoint;
		}
		else if (shape == Qt::SizeVerCursor)
		{
			_startPoint = event->pos();
			_endPoint = _startPoint;
		}
		else if (shape == Qt::SizeBDiagCursor)
		{
			_startPoint = event->pos();
			_endPoint = _startPoint;
		}
		else if (shape == Qt::SizeFDiagCursor)
		{
			_startPoint = event->pos();
			_endPoint = _startPoint;
		}
	}

	update();
}

void VideoView::mouseMoveEvent(QMouseEvent *event)
{
	Sequence* sequence = _project->getActiveSequence();

	if (!sequence) return;

	if (_status == VW_STATUS_DISPLAYING)
	{
		setCursor(QCursor(Qt::ArrowCursor));
		if (event->buttons() & Qt::LeftButton)
		{
			if (_dragingRect)
			{
				_endPoint = event->pos();
				update();
			}
		}
	}
	else if (_status == VW_STATUS_EDITING)
	{
		if (event->buttons() == Qt::NoButton)
		{
			QPoint mpt = event->pos();

			std::vector<TrackedObject*>* objects = sequence->getTrackedObjects();

			bool horizentalCursor = false;
			bool verticalCursor = false;
			bool northEastCursor = false;
			bool northWestCursor = false;

			//// North East cursor
			//bool neCursor = false;

			//// North West cursor
			//bool nwCursor = false;

			// Moving cursor
			bool mvCursor = false;

			for (int i = 0; i < objects->size(); i++)
			{
				TrackedObject* tobj = objects->at(i);

				if (_frameIndex < tobj->getStartFrameIndex() || _frameIndex > tobj->getEndFrameIndex())
					continue;

				Shape* shape = tobj->getShape(_frameIndex);

				
				if (ShapeFish* shapeFish = dynamic_cast<ShapeFish*>(shape))
				{
					if (tobj->isSelected())
					{
						if (shapeFish->getSelectStatus() == SFS_NONE)
						{
							cv::Rect2d crect = tobj->getRect(_frameIndex);
							QRect qrect = cvRect2QRect(crect);

							if (((abs(qrect.x() - mpt.x()) < cursorDist) || (abs(qrect.x() + qrect.width() - mpt.x()) < cursorDist))
								&& ((mpt.y() - qrect.y() > cursorDist) && (qrect.y() + qrect.height() - cursorDist > mpt.y())))
								horizentalCursor = true;
							else if (((abs(qrect.y() - mpt.y()) < cursorDist) || (abs(qrect.y() + qrect.height() - mpt.y()) < cursorDist))
								&& ((mpt.x() - qrect.x() > cursorDist) && (qrect.x() + qrect.width() - cursorDist > mpt.x())))
								verticalCursor = true;
							else if ((mpt.x() > qrect.x() + cursorDist) &&
								(qrect.x() + qrect.width() - cursorDist > mpt.x()) &&
								(mpt.y() > qrect.y() + cursorDist) &&
								(qrect.y() + qrect.height() - cursorDist > mpt.y()))
								mvCursor = true;
						}
						else if (shapeFish->getSelectStatus() == SFS_HEAD)
						{
							cv::Rect2d crect = tobj->getRect(_frameIndex);

							// Draw Select Status of Rectangle
							float refSize = vmin(crect.width, crect.height) * FISH_ICON_RATIO;
							float refSize2 = refSize * 2.0;

							QPoint pt = cvPoint2QPoint(shapeFish->getHeadCenter());

							if (mpt.x() >= pt.x() - refSize2 &&
								mpt.x() <= pt.x() + refSize2 &&
								mpt.y() >= pt.y() - refSize2 &&
								mpt.y() <= pt.y() + refSize2)
							{
								mvCursor = true;
							}
						}
						else if (shapeFish->getSelectStatus() == SFS_MASS)
						{
							cv::Rect2d crect = tobj->getRect(_frameIndex);

							// Draw Select Status of Rectangle
							float refSize = vmin(crect.width, crect.height) * FISH_ICON_RATIO;
							float refSize2 = refSize * 2.0;

							QPoint pt = cvPoint2QPoint(shapeFish->getMassCenter());

							if (mpt.x() >= pt.x() - refSize2 &&
								mpt.x() <= pt.x() + refSize2 &&
								mpt.y() >= pt.y() - refSize2 &&
								mpt.y() <= pt.y() + refSize2)
							{
								mvCursor = true;
							}
						}
					}
				}
				else if (ShapeRect* shapeRect = dynamic_cast<ShapeRect*>(shape))
				{
					if (tobj->isSelected())
					{
						cv::Rect2d crect = tobj->getRect(_frameIndex);
						QRect qrect = cvRect2QRect(crect);

						if (((abs(qrect.left() - mpt.x()) < cursorDist) || (abs(qrect.right() - mpt.x()) < cursorDist))
							&& ((mpt.y() - qrect.top() > cursorDist) && (qrect.bottom() - cursorDist > mpt.y())))
							horizentalCursor = true;
						else if (((abs(qrect.top() - mpt.y()) < cursorDist) || (abs(qrect.bottom() - mpt.y()) < cursorDist))
							&& ((mpt.x() - qrect.left() > cursorDist) && (qrect.right() - cursorDist > mpt.x())))
							verticalCursor = true;
						else if (((abs(qrect.left() - mpt.x()) < cursorDist) && (abs(qrect.top() - mpt.y()) < cursorDist)) ||
							(abs(qrect.right() - mpt.x()) < cursorDist && (abs(qrect.bottom() - mpt.y()) < cursorDist)))
							northWestCursor = true;
						else if (((abs(qrect.left() - mpt.x()) < cursorDist) && (abs(qrect.bottom() - mpt.y()) < cursorDist)) ||
							((abs(qrect.right() - mpt.x()) < cursorDist) && (abs(qrect.top() - mpt.y()) < cursorDist)))
							northEastCursor = true;
						else if ((mpt.x() > qrect.x() + cursorDist) &&
							(qrect.x() + qrect.width() - cursorDist > mpt.x()) &&
							(mpt.y() > qrect.y() + cursorDist) &&
							(qrect.y() + qrect.height() - cursorDist > mpt.y()))
							mvCursor = true;
					}
				}
				else
				{

					if (tobj->isSelected())
					{
						cv::Rect2d crect = tobj->getRect(_frameIndex);
						QRect qrect = cvRect2QRect(crect);

						if (((abs(qrect.x() - mpt.x()) < cursorDist) || (abs(qrect.x() + qrect.width() - mpt.x()) < cursorDist))
							&& ((mpt.y() - qrect.y() > cursorDist) && (qrect.y() + qrect.height() - cursorDist > mpt.y())))
							horizentalCursor = true;
						else if (((abs(qrect.y() - mpt.y()) < cursorDist) || (abs(qrect.y() + qrect.height() - mpt.y()) < cursorDist))
							&& ((mpt.x() - qrect.x() > cursorDist) && (qrect.x() + qrect.width() - cursorDist > mpt.x())))
							verticalCursor = true;
						else if ((mpt.x() > qrect.x() + cursorDist) &&
							(qrect.x() + qrect.width() - cursorDist > mpt.x()) &&
							(mpt.y() > qrect.y() + cursorDist) &&
							(qrect.y() + qrect.height() - cursorDist > mpt.y()))
							mvCursor = true;
					}
				}
			}

			if (horizentalCursor)
				setCursor(QCursor(Qt::SizeHorCursor));
			else if (verticalCursor)
				setCursor(QCursor(Qt::SizeVerCursor));
			else if (northEastCursor)
				setCursor(QCursor(Qt::SizeBDiagCursor));
			else if (northWestCursor)
				setCursor(QCursor(Qt::SizeFDiagCursor));
			else if (mvCursor)
				setCursor(QCursor(Qt::SizeAllCursor));
			else
				setCursor(QCursor(Qt::ArrowCursor));
		}
		else if( event->buttons() & Qt::LeftButton )
		{
			Qt::CursorShape shape = cursor().shape();

			if (shape == Qt::SizeAllCursor || shape == Qt::SizeHorCursor || shape == Qt::SizeVerCursor
				|| shape == Qt::SizeBDiagCursor || shape == Qt::SizeFDiagCursor)
			{
				_endPoint = event->pos();
			}

			update();
		}
	}
	else if (_status == ViewStatus::VW_STATUS_FRAME_DRAGING)
	{
		//setCursor(QCursor(Qt::SizeAllCursor));

		if ( (event->buttons() & Qt::LeftButton || (event->buttons()) & Qt::RightButton))
		{
			_endPoint = event->pos();
			update();
		}
    }
}

void VideoView::mouseReleaseEvent(QMouseEvent *event)
{	
	Sequence* sequence = _project->getActiveSequence();

	if (!sequence) return;

	if (_status == VW_STATUS_DISPLAYING)
	{
		if (_dragingRect)
		{
			_endPoint = event->pos();

			if (abs(_startPoint.x() - _endPoint.x()) > 20 && abs(_startPoint.y() - _endPoint.y()) > 20)
			{
				_rects.push_back(QRect(_startPoint, _endPoint));

				
				_endPoint = _startPoint;

				if (_rects.size() > 0)
					emit rectAdded();
			}
			
			_dragingRect = false;
		}
	}
	else if( _status == VW_STATUS_EDITING )
	{
		_endPoint = event->pos();

		if (event->button() == Qt::LeftButton)
		{
			TrackedObject* tobj = nullptr;
			std::vector<TrackedObject*>* objects = sequence->getTrackedObjects();

			for (int i = 0; i < objects->size(); i++)
			{
				tobj = objects->at(i);

				if (tobj->isSelected())
					break;
			}

			if (tobj == nullptr)
				return;

			Qt::CursorShape shape = cursor().shape();
			
			if (shape == Qt::SizeAllCursor)
			{
				cv::Rect2d rect = tobj->getRect(_frameIndex);

				QPoint pt = _endPoint - _startPoint;

				//cv::Point2d cpt = qPoint2cvPoint(pt);
				cv::Point2d cpt = qOffset2cvPoint(pt);

				rect.x += cpt.x;
				rect.y += cpt.y;

				Shape* shape = tobj->getShape(_frameIndex);

				if (ShapeFish* shapeFish = dynamic_cast<ShapeFish*>(shape))
				{
					cv::Point2d hpt = shapeFish->getHeadCenter();
					cv::Point2d mpt = shapeFish->getMassCenter();

					if (shapeFish->getSelectStatus() == SFS_HEAD)
						shapeFish->setHeadCenter(hpt + cpt);
					else if (shapeFish->getSelectStatus() == SFS_MASS)
						shapeFish->setMassCenter(mpt + cpt);
					else
					{
						shapeFish->setRect(rect);
						shapeFish->setHeadCenter(hpt + cpt);
						shapeFish->setMassCenter(mpt + cpt);
					}
				}				
				else if (ShapeRect* shapeRect = dynamic_cast<ShapeRect*>(shape))
					shapeRect->setRect(rect);

				_startPoint = _endPoint;
			}
			else if (shape == Qt::SizeHorCursor)
			{
				cv::Rect2d crect = tobj->getRect(_frameIndex);
				QRect qrect = cvRect2QRect(crect);

				QPoint pt = _endPoint - _startPoint;
				cv::Point2d cpt = qPoint2cvPoint(pt);

				QRect trect;

				if (abs(_startPoint.x() - qrect.x()) <= cursorDist)
				{
					trect.setX(qrect.x() + pt.x());
					trect.setY(qrect.y());
					trect.setWidth(qrect.width() - pt.x());
					trect.setHeight(qrect.height());
				}
				else
				{
					trect.setX(qrect.x());
					trect.setY(qrect.y());
					trect.setWidth(qrect.width() + pt.x());
					trect.setHeight(qrect.height());
				}

				cv::Rect2d nrect = qRect2cvRect(trect);
                
				Shape* objShape = tobj->getShape(_frameIndex);
				objShape->setRect(nrect);

				_startPoint = _endPoint;
			}
			else if (shape == Qt::SizeVerCursor)
			{
				cv::Rect2d crect = tobj->getRect(_frameIndex);
				QRect qrect = cvRect2QRect(crect);

				QPoint pt = _endPoint - _startPoint;
				cv::Point2d cpt = qPoint2cvPoint(pt);

				QRect trect;

				if (abs(_startPoint.y() - qrect.y()) <= cursorDist)
				{
					trect.setX(qrect.x());
					trect.setY(qrect.y() + pt.y());
					trect.setWidth(qrect.width());
					trect.setHeight(qrect.height() - pt.y());
				}
				else
				{
					trect.setX(qrect.x());
					trect.setY(qrect.y());
					trect.setWidth(qrect.width());
					trect.setHeight(qrect.height() + pt.y());
				}

				cv::Rect2d nrect = qRect2cvRect(trect);

				Shape* objShape = tobj->getShape(_frameIndex);
				objShape->setRect(nrect);

				_startPoint = _endPoint;
			}
			if (shape == Qt::SizeBDiagCursor || shape == Qt::SizeFDiagCursor)
			{
				cv::Rect2d crect = tobj->getRect(_frameIndex);
				QRect qrect = cvRect2QRect(crect);

				QPoint pt = _endPoint - _startPoint;
				cv::Point2d cpt = qPoint2cvPoint(pt);

				QRect trect;

				int nx = 0;
				int ny = 0;
				int nw = 0;
				int nh = 0;

				if (fabs(_startPoint.x() - qrect.left()) <= fabs(_startPoint.x() - qrect.right()))
				{
					nx = qrect.left() + (_endPoint.x() - _startPoint.x());
					nw = qrect.width() - (_endPoint.x() - _startPoint.x());
				}
				else
				{
					nx = qrect.left();
					nw = qrect.width() + (_endPoint.x() - _startPoint.x());
				}

				if (fabs(_startPoint.y() - qrect.top()) <= fabs(_startPoint.y() - qrect.bottom()))
				{
					ny = qrect.top() + (_endPoint.y() - _startPoint.y());
					nh = qrect.height() - (_endPoint.y() - _startPoint.y());
				}
				else
				{
					ny = qrect.top();
					nh = qrect.height() + (_endPoint.y() - _startPoint.y());
				}

				trect.setX(nx);
				trect.setY(ny);
				trect.setWidth(nw);
				trect.setHeight(nh);

				cv::Rect2d nrect = qRect2cvRect(trect);

				Shape* objShape = tobj->getShape(_frameIndex);
				objShape->setRect(nrect);

				_startPoint = _endPoint;
			}

			update();
		}
	}
	else if (_status == ViewStatus::VW_STATUS_FRAME_DRAGING)
	{
		_endPoint = event->pos();

		_zoomOffset.setX(_zoomOffset.x() + _endPoint.x() - _startPoint.x());
		_zoomOffset.setY(_zoomOffset.y() + _endPoint.y() - _startPoint.y());

		_startPoint = _endPoint;

		_status = _prevStatus;

		update();
	}
}

QRect VideoView::cvRect2QRect(cv::Rect2d rect)
{
	QRect geoRect = geometry();

	QRect result;

	Sequence* sequence = _project->getActiveSequence();

	if (!sequence) return result;	

	QRect imageQRect = getImageQRect();

	result.setX(imageQRect.x() + rect.x / sequence->getVideoWidth() * imageQRect.width());
	result.setY(imageQRect.y() + rect.y / sequence->getVideoHeight() * imageQRect.height());
	result.setWidth(rect.width / sequence->getVideoWidth() * imageQRect.width());
	result.setHeight(rect.height / sequence->getVideoHeight() * imageQRect.height());

	return result;
}

cv::Rect2d VideoView::qRect2cvRect(QRect rect)
{
	QRect geoRect = geometry();

	cv::Rect2d result;

	Sequence* sequence = _project->getActiveSequence();

	if (!sequence) return result;

	QRect imageQRect = getImageQRect();

	result.x = (rect.x() - imageQRect.x()) * 1.0 / imageQRect.width() * sequence->getVideoWidth();
	result.y = (rect.y() - imageQRect.y()) * 1.0 / imageQRect.height() * sequence->getVideoHeight();

	result.width = rect.width() * 1.0 / imageQRect.width() * sequence->getVideoWidth();
	result.height = rect.height() * 1.0 / imageQRect.height() * sequence->getVideoHeight();

	if (result.width < 0.0)
	{
		result.x += result.width;
		result.width = -result.width;
	}

	if (result.height < 0.0)
	{
		result.y += result.height;
		result.height = -result.height;
	}

	return result;
}

cv::Point2d VideoView::qPoint2cvPoint(QPoint qpt)
{
	cv::Point2d pt;

	Sequence* sequence = _project->getActiveSequence();

	if (!sequence) return pt;

	QRect imageQRect = getImageQRect();

	pt.x = (qpt.x() - imageQRect.x()) * 1.0 / imageQRect.width() * sequence->getVideoWidth();
	pt.y = (qpt.y() - imageQRect.y()) * 1.0 / imageQRect.height() * sequence->getVideoHeight();

	//pt.x = qpt.x() * 1.0 / width() * sequence->getVideoWidth();
	//pt.y = qpt.y() * 1.0 / height() * sequence->getVideoHeight();

	return pt;
}

cv::Point2d VideoView::qOffset2cvPoint(QPoint qpt)
{
	cv::Point2d pt;

	Sequence* sequence = _project->getActiveSequence();

	if (!sequence) return pt;

	QRect imageQRect = getImageQRect();

	pt.x = (qpt.x()) * 1.0 / imageQRect.width() * sequence->getVideoWidth();
	pt.y = (qpt.y()) * 1.0 / imageQRect.height() * sequence->getVideoHeight();

	//pt.x = qpt.x() * 1.0 / width() * sequence->getVideoWidth();
	//pt.y = qpt.y() * 1.0 / height() * sequence->getVideoHeight();

	return pt;
}

QPoint VideoView::cvPoint2QPoint(cv::Point2d cpt)
{
	QPoint pt;

	Sequence* sequence = _project->getActiveSequence();

	if (!sequence) return pt;

	QRect imageQRect = getImageQRect();

	pt.setX(imageQRect.x() + cpt.x * 1.0 / sequence->getVideoWidth() * imageQRect.width());
	pt.setY(imageQRect.y() + cpt.y * 1.0 / sequence->getVideoHeight() * imageQRect.height());

	return pt;
}

std::vector<cv::Rect2d> VideoView::getCvRects()
{
	std::vector<cv::Rect2d> results;

	for (int i = 0; i < _rects.size(); i++)
	{
		results.push_back(qRect2cvRect(_rects.at(i)));
	}

	return results;
}

void VideoView::drawNewObject(QPainter& painter)
{
	if (_project->getProjectType() == TYPE_RECTANGLE)
		drawNewObjectRect(painter);
	else if (_project->getProjectType() == TYPE_FISH)
		drawNewObjectFish(painter);
}

void VideoView::drawNewObjectRect(QPainter& painter)
{
	QPen pen;
	pen.setStyle(Qt::SolidLine);
	pen.setWidth(3);
	pen.setColor(QColor(255, 255, 0, 127));
	painter.setPen(pen);

	if (_dragingRect)
	{
		painter.drawRect(QRect(_startPoint, _endPoint));
	}

	for (int i = 0; i < _rects.size(); i++)
	{		
		painter.drawRect(_rects.at(i));
	}
}

void VideoView::drawNewObjectFish(QPainter& painter)
{
	QPen pen;
	pen.setStyle(Qt::SolidLine);
	pen.setWidth(3);
	pen.setColor(QColor(255, 255, 0, 127));
	painter.setPen(pen);


	if (_dragingRect)
	{
		QPoint headCenter;
		QPoint massCenter;

		headCenter.setX(_startPoint.x() + (_endPoint.x() - _startPoint.x()) * 0.2);
		headCenter.setY(_startPoint.y() + (_endPoint.y() - _startPoint.y()) * 0.5);

		massCenter.setX(_startPoint.x() + (_endPoint.x() - _startPoint.x()) * 0.5);
		massCenter.setY(headCenter.y());

		painter.drawRect(QRect(_startPoint, _endPoint));

		painter.drawLine(QPoint(headCenter.x() - 10, headCenter.y()), QPoint(headCenter.x() + 10, headCenter.y()));
		painter.drawLine(QPoint(headCenter.x(), headCenter.y() - 10), QPoint(headCenter.x(), headCenter.y() + 10));

		//painter.drawRect(QRect(_startPoint, _endPoint));

		painter.drawLine(QPoint(massCenter.x() - 10, massCenter.y()), QPoint(massCenter.x() + 10, massCenter.y()));
		painter.drawLine(QPoint(massCenter.x(), massCenter.y() - 10), QPoint(massCenter.x(), massCenter.y() + 10));

	}

	for (int i = 0; i < _rects.size(); i++)
	{
		QPoint headCenter;
		QPoint massCenter;

		QRect rect = _rects.at(i);
		
		headCenter.setX(rect.x() + rect.width() * 0.2);
		headCenter.setY(rect.y() + rect.height() * 0.5);

		massCenter.setX(rect.x() + rect.width() * 0.5);
		massCenter.setY(rect.y() + rect.height() * 0.5);

		painter.drawRect(_rects.at(i));

		painter.drawLine(QPoint(headCenter.x() - 10, headCenter.y()), QPoint(headCenter.x() + 10, headCenter.y()));
		painter.drawLine(QPoint(headCenter.x(), headCenter.y() - 10), QPoint(headCenter.x(), headCenter.y() + 10));

		painter.drawLine(QPoint(massCenter.x() - 10, massCenter.y()), QPoint(massCenter.x() + 10, massCenter.y()));
		painter.drawLine(QPoint(massCenter.x(), massCenter.y() - 10), QPoint(massCenter.x(), massCenter.y() + 10));

	}
}

void VideoView::drawTrackingObject(QPainter& painter)
{
	//Draw Tracking Box
	Sequence* sequence = _project->getActiveSequence();

	if (!sequence) return;

	std::vector<TrackedObject*>* objects = sequence->getTrackingObjects();

	QPen pen;
	pen.setStyle(Qt::SolidLine);
	pen.setWidth(3);
	pen.setColor(QColor(255, 0, 0, 127));
	painter.setPen(pen);

	for (int i = 0; i < objects->size(); i++)
	{
		TrackedObject* tobj = objects->at(i);

		cv::Rect2d crect = tobj->getRect(_frameIndex);

		QRect rect = cvRect2QRect(crect);

		painter.drawRect(rect);
	}
}

void VideoView::drawTrackedObject(QPainter& painter)
{
	Sequence* sequence = _project->getActiveSequence();

	if (!sequence) return;

	std::vector<TrackedObject*>* objects = sequence->getTrackedObjects();

	bool noSelectedObjectToDraw = true;

	for (int i = 0; i < objects->size(); i++)
	{
		TrackedObject* tobj = objects->at(i);

		if (tobj->isSelected() && tobj->isVisible())
			noSelectedObjectToDraw = false;

		if (!tobj->isVisible()) continue;

		if (_frameIndex < tobj->getStartFrameIndex() || _frameIndex > tobj->getEndFrameIndex())
			continue;

        if(_project->getProjectType() == TYPE_RECTANGLE)
            drawTrackedObjectRect(painter, tobj);
        else if(_project->getProjectType()==TYPE_FISH)
            drawTrackedObjectFish(painter, tobj);
	}

	if (noSelectedObjectToDraw)
	{
		sequence->desectAllTrackedObjects();
	}
}

void VideoView::drawSelectedObjectRect(QPainter& painter, QRect& rect)
{
	int rectWidth = 9;

	// rect 0
	QRect drect;
	
	drect.setX(rect.x() - rectWidth / 2);
	drect.setY(rect.y() - rectWidth / 2);
	drect.setWidth(rectWidth);
	drect.setHeight(rectWidth);

	painter.drawRect(drect);


	// rect 1
	drect.setX(rect.x() + rect.width() / 2 - rectWidth / 2);
	drect.setY(rect.y() - rectWidth / 2);
	drect.setWidth(rectWidth);
	drect.setHeight(rectWidth);
	painter.drawRect(drect);

	// rect 2
	drect.setX(rect.x() + rect.width() - rectWidth / 2);
	drect.setY(rect.y() - rectWidth / 2);
	drect.setWidth(rectWidth);
	drect.setHeight(rectWidth);
	painter.drawRect(drect);

	// rect 3
	drect.setX(rect.x() - rectWidth / 2);
	drect.setY(rect.y() + rect.height() / 2 - rectWidth / 2);
	drect.setWidth(rectWidth);
	drect.setHeight(rectWidth);
	painter.drawRect(drect);

	// rect 4
	//drect.setX(rect.x() + rect.width() / 2 - rectWidth / 2);
	//drect.setY(rect.y() + rect.height() / 2 - rectWidth / 2);
	//drect.setWidth(rectWidth);
	//drect.setHeight(rectWidth);
	//painter.drawRect(drect);

	// rect 5
	drect.setX(rect.x() + rect.width() - rectWidth / 2);
	drect.setY(rect.y() + rect.height() / 2 - rectWidth / 2);
	drect.setWidth(rectWidth);
	drect.setHeight(rectWidth);
	painter.drawRect(drect);

	// rect 6
	drect.setX(rect.x() - rectWidth / 2);
	drect.setY(rect.y() + rect.height() - rectWidth / 2);
	drect.setWidth(rectWidth);
	drect.setHeight(rectWidth);
	painter.drawRect(drect);

	// rect 7
	drect.setX(rect.x() + rect.width() / 2 - rectWidth / 2);
	drect.setY(rect.y() + rect.height() - rectWidth / 2);
	drect.setWidth(rectWidth);
	drect.setHeight(rectWidth);
	painter.drawRect(drect);

	// rect 8
	drect.setX(rect.x() + rect.width() - rectWidth / 2);
	drect.setY(rect.y() + rect.height() - rectWidth / 2);
	drect.setWidth(rectWidth);
	drect.setHeight(rectWidth);
	painter.drawRect(drect);

	// draw editing rect
	Qt::CursorShape shape = cursor().shape();

	if (shape == Qt::SizeAllCursor && _status == ViewStatus::VW_STATUS_EDITING)
	{
		QRect trect;
		trect.setX(rect.x() + (_endPoint.x() - _startPoint.x()));
		trect.setY(rect.y() + (_endPoint.y() - _startPoint.y()));
		trect.setWidth(rect.width());
		trect.setHeight(rect.height());

		painter.drawRect(trect);
	}
	else if (shape == Qt::SizeHorCursor)
	{
		int tx = _endPoint.x() - _startPoint.x();
		QRect trect;

		if (abs(_startPoint.x() - rect.x()) <= cursorDist)
		{
			trect.setX(rect.x() + tx);
			trect.setY(rect.y());
			trect.setWidth(rect.width() - tx);
			trect.setHeight(rect.height());
		}
		else
		{
			trect.setX(rect.x());
			trect.setY(rect.y());
			trect.setWidth(rect.width() + tx);
			trect.setHeight(rect.height());		
		}
		//painter.drawRect(trect);
		drawEditingObjectRect(painter, trect);
	}
	else if (shape == Qt::SizeVerCursor)
	{
		int ty = _endPoint.y() - _startPoint.y();
		QRect trect;

		if (abs(_startPoint.y() - rect.y()) <= cursorDist)
		{
			trect.setX(rect.x());
			trect.setY(rect.y() + ty);
			trect.setWidth(rect.width());
			trect.setHeight(rect.height() - ty);
		}
		else
		{
			trect.setX(rect.x());
			trect.setY(rect.y());
			trect.setWidth(rect.width());
			trect.setHeight(rect.height() + ty);
		}

		//painter.drawRect(trect);
		drawEditingObjectRect(painter, trect);
	}
	else if (shape == Qt::SizeBDiagCursor || shape == Qt::SizeFDiagCursor )
	{
		int nx = 0;
		int ny = 0;
		int nw = 0;
		int nh = 0;

		QRect trect;

		if (fabs(_startPoint.x() - rect.left()) <= fabs(_startPoint.x() - rect.right()))
		{
			nx = rect.left() + (_endPoint.x() - _startPoint.x());
			nw = rect.width() - (_endPoint.x() - _startPoint.x());
		}
		else
		{
			nx = rect.left();
			nw = rect.width() + (_endPoint.x() - _startPoint.x());
		}

		if (fabs(_startPoint.y() - rect.top()) <= fabs(_startPoint.y() - rect.bottom()))
		{
			ny = rect.top() + (_endPoint.y() - _startPoint.y());
			nh = rect.height() - (_endPoint.y() - _startPoint.y());
		}
		else
		{
			ny = rect.top();
			nh = rect.height() + (_endPoint.y() - _startPoint.y());
		}

		trect.setX(nx);
		trect.setY(ny);
		trect.setWidth(nw);
		trect.setHeight(nh);

		//painter.drawRect(trect);
		drawEditingObjectRect(painter, trect);
	}		
}

void VideoView::drawEditingObjectRect(QPainter& painter, QRect& rect)
{
	if (QGuiApplication::mouseButtons() != Qt::LeftButton)
		return;

	Qt::CursorShape shape = cursor().shape();

	QPen redPen;
	redPen.setStyle(Qt::SolidLine);
	redPen.setWidth(3);
	redPen.setColor(QColor(255, 0, 0, 255));

	QPen bluePen;
	bluePen.setStyle(Qt::SolidLine);
	bluePen.setWidth(3);
	bluePen.setColor(QColor(0, 0, 255, 127));

	painter.setPen(bluePen);

	if (shape == Qt::SizeHorCursor)
	{
		if (fabs(_endPoint.x() - rect.left()) <= fabs(_endPoint.x() - rect.right()))
		{
			painter.drawLine(rect.left(), rect.top(), rect.right(), rect.top());
			painter.drawLine(rect.right(), rect.top(), rect.right(), rect.bottom());
			painter.drawLine(rect.right(), rect.bottom(), rect.left(), rect.bottom());

			painter.setPen(redPen);
			painter.drawLine(rect.left(), rect.bottom(), rect.left(), rect.top());			
		}
		else
		{
			painter.drawLine(rect.left(), rect.top(), rect.right(), rect.top());
			painter.setPen(redPen);
			painter.drawLine(rect.right(), rect.top(), rect.right(), rect.bottom());
			painter.setPen(bluePen);
			painter.drawLine(rect.right(), rect.bottom(), rect.left(), rect.bottom());
			painter.drawLine(rect.left(), rect.bottom(), rect.left(), rect.top());
		}
	}
	else if (shape == Qt::SizeVerCursor)
	{
		if (fabs(_endPoint.y() - rect.top()) <= fabs(_endPoint.y() - rect.bottom()))
		{
			painter.setPen(redPen);
			painter.drawLine(rect.left(), rect.top(), rect.right(), rect.top());		
			painter.setPen(bluePen);
			painter.drawLine(rect.right(), rect.top(), rect.right(), rect.bottom());
			painter.drawLine(rect.right(), rect.bottom(), rect.left(), rect.bottom());
			painter.drawLine(rect.left(), rect.bottom(), rect.left(), rect.top());
		}
		else
		{
			painter.drawLine(rect.left(), rect.top(), rect.right(), rect.top());
			painter.drawLine(rect.right(), rect.top(), rect.right(), rect.bottom());
			painter.setPen(redPen);
			painter.drawLine(rect.right(), rect.bottom(), rect.left(), rect.bottom());
			painter.setPen(bluePen);
			painter.drawLine(rect.left(), rect.bottom(), rect.left(), rect.top());
		}

	}
	else if (shape == Qt::SizeFDiagCursor)
	{
		int x1 = rect.left(); 
		int x2 = rect.right();
		int y1 = rect.top();
		int y2 = rect.bottom();

		float dst1 = (_endPoint.x() - x1) * (_endPoint.x() - x1) + (_endPoint.y() - y1) * (_endPoint.y() - y1);
		float dst2 = (_endPoint.x() - x2) * (_endPoint.x() - x2) + (_endPoint.y() - y2) * (_endPoint.y() - y2);

		if (dst1 <= dst2)
		{
			painter.setPen(redPen);
			painter.drawLine(rect.left(), rect.top(), rect.right(), rect.top());
			painter.setPen(bluePen);
			painter.drawLine(rect.right(), rect.top(), rect.right(), rect.bottom());			
			painter.drawLine(rect.right(), rect.bottom(), rect.left(), rect.bottom());
			painter.setPen(redPen);
			painter.drawLine(rect.left(), rect.bottom(), rect.left(), rect.top());
		}
		else
		{
			painter.setPen(bluePen);
			painter.drawLine(rect.left(), rect.top(), rect.right(), rect.top());
			painter.setPen(redPen);
			painter.drawLine(rect.right(), rect.top(), rect.right(), rect.bottom());
			painter.drawLine(rect.right(), rect.bottom(), rect.left(), rect.bottom());
			painter.setPen(bluePen);
			painter.drawLine(rect.left(), rect.bottom(), rect.left(), rect.top());
		}
	}
	else if (shape == Qt::SizeBDiagCursor)
	{
		int x1 = rect.right();
		int x2 = rect.left();
		int y1 = rect.top();
		int y2 = rect.bottom();

		float dst1 = (_endPoint.x() - x1) * (_endPoint.x() - x1) + (_endPoint.y() - y1) * (_endPoint.y() - y1);
		float dst2 = (_endPoint.x() - x2) * (_endPoint.x() - x2) + (_endPoint.y() - y2) * (_endPoint.y() - y2);

		if (dst1 <= dst2)
		{
			painter.setPen(redPen);
			painter.drawLine(rect.left(), rect.top(), rect.right(), rect.top());			
			painter.drawLine(rect.right(), rect.top(), rect.right(), rect.bottom());
			painter.setPen(bluePen);
			painter.drawLine(rect.right(), rect.bottom(), rect.left(), rect.bottom());
			painter.drawLine(rect.left(), rect.bottom(), rect.left(), rect.top());
		}
		else
		{
			painter.setPen(bluePen);
			painter.drawLine(rect.left(), rect.top(), rect.right(), rect.top());
			painter.drawLine(rect.right(), rect.top(), rect.right(), rect.bottom());
			painter.setPen(redPen);
			painter.drawLine(rect.right(), rect.bottom(), rect.left(), rect.bottom());
			painter.drawLine(rect.left(), rect.bottom(), rect.left(), rect.top());
		}
	}
}

void VideoView::drawSelectedObjectFish(QPainter& painter, ShapeFish* shapeFish)
{
	int rectWidth = 9;

	cv::Rect2d crect = shapeFish->getRect();
	QRect rect = cvRect2QRect(crect);

	if (shapeFish->getSelectStatus() == SFS_NONE)
	{
		// rect 0
		QRect drect;

		drect.setX(rect.x() - rectWidth / 2);
		drect.setY(rect.y() - rectWidth / 2);
		drect.setWidth(rectWidth);
		drect.setHeight(rectWidth);

		painter.drawRect(drect);

		// rect 1
		drect.setX(rect.x() + rect.width() / 2 - rectWidth / 2);
		drect.setY(rect.y() - rectWidth / 2);
		drect.setWidth(rectWidth);
		drect.setHeight(rectWidth);
		painter.drawRect(drect);

		// rect 2
		drect.setX(rect.x() + rect.width() - rectWidth / 2);
		drect.setY(rect.y() - rectWidth / 2);
		drect.setWidth(rectWidth);
		drect.setHeight(rectWidth);
		painter.drawRect(drect);

		// rect 3
		drect.setX(rect.x() - rectWidth / 2);
		drect.setY(rect.y() + rect.height() / 2 - rectWidth / 2);
		drect.setWidth(rectWidth);
		drect.setHeight(rectWidth);
		painter.drawRect(drect);

		// rect 4
		//drect.setX(rect.x() + rect.width() / 2 - rectWidth / 2);
		//drect.setY(rect.y() + rect.height() / 2 - rectWidth / 2);
		//drect.setWidth(rectWidth);
		//drect.setHeight(rectWidth);
		//painter.drawRect(drect);

		// rect 5
		drect.setX(rect.x() + rect.width() - rectWidth / 2);
		drect.setY(rect.y() + rect.height() / 2 - rectWidth / 2);
		drect.setWidth(rectWidth);
		drect.setHeight(rectWidth);
		painter.drawRect(drect);

		// rect 6
		drect.setX(rect.x() - rectWidth / 2);
		drect.setY(rect.y() + rect.height() - rectWidth / 2);
		drect.setWidth(rectWidth);
		drect.setHeight(rectWidth);
		painter.drawRect(drect);

		// rect 7
		drect.setX(rect.x() + rect.width() / 2 - rectWidth / 2);
		drect.setY(rect.y() + rect.height() - rectWidth / 2);
		drect.setWidth(rectWidth);
		drect.setHeight(rectWidth);
		painter.drawRect(drect);

		// rect 8
		drect.setX(rect.x() + rect.width() - rectWidth / 2);
		drect.setY(rect.y() + rect.height() - rectWidth / 2);
		drect.setWidth(rectWidth);
		drect.setHeight(rectWidth);
		painter.drawRect(drect);

		// draw editing rect
		Qt::CursorShape shape = cursor().shape();

		if (shape == Qt::SizeAllCursor)
		{
			QRect trect;
			trect.setX(rect.x() + (_endPoint.x() - _startPoint.x()));
			trect.setY(rect.y() + (_endPoint.y() - _startPoint.y()));
			trect.setWidth(rect.width());
			trect.setHeight(rect.height());

			painter.drawRect(trect);
		}
		else if (shape == Qt::SizeHorCursor)
		{
			int tx = _endPoint.x() - _startPoint.x();
			QRect trect;

			if (abs(_startPoint.x() - rect.x()) <= cursorDist)
			{
				trect.setX(rect.x() + tx);
				trect.setY(rect.y());
				trect.setWidth(rect.width() - tx);
				trect.setHeight(rect.height());
			}
			else
			{
				trect.setX(rect.x());
				trect.setY(rect.y());
				trect.setWidth(rect.width() + tx);
				trect.setHeight(rect.height());
			}
			painter.drawRect(trect);
		}
		else if (shape == Qt::SizeVerCursor)
		{
			int ty = _endPoint.y() - _startPoint.y();
			QRect trect;

			if (abs(_startPoint.y() - rect.y()) <= cursorDist)
			{
				trect.setX(rect.x());
				trect.setY(rect.y() + ty);
				trect.setWidth(rect.width());
				trect.setHeight(rect.height() - ty);
			}
			else
			{
				trect.setX(rect.x());
				trect.setY(rect.y());
				trect.setWidth(rect.width());
				trect.setHeight(rect.height() + ty);
			}

			painter.drawRect(trect);
		}
	}

	if (shapeFish->getSelectStatus() == SFS_HEAD || shapeFish->getSelectStatus() == SFS_MASS)
	{
		// Draw Select Status of Rectangle
		float refSize = vmin(crect.width, crect.height) * FISH_ICON_RATIO;
		float refSize2 = refSize * 2.0;

		QPolygon polygon;

		cv::Point2d pt;

		if (shapeFish->getSelectStatus() == SFS_HEAD)
			pt = shapeFish->getHeadCenter();
		else
			pt = shapeFish->getMassCenter();

		std::vector<QPoint> points;

		QPoint pt1 = cvPoint2QPoint(cv::Point2d(pt.x - refSize2, pt.y - refSize2));
		QPoint pt2 = cvPoint2QPoint(cv::Point2d(pt.x + refSize2, pt.y - refSize2));
		QPoint pt3 = cvPoint2QPoint(cv::Point2d(pt.x + refSize2, pt.y + refSize2));
		QPoint pt4 = cvPoint2QPoint(cv::Point2d(pt.x - refSize2, pt.y + refSize2));

		points.push_back(pt1);
		points.push_back(pt2);
		points.push_back(pt3);
		points.push_back(pt4);

		for (int i = 0; i < 4; i++)
		{
			QPoint rpt = points.at(i);

			QRect trect;
			trect.setX(rpt.x() - rectWidth / 2);
			trect.setY(rpt.y() - rectWidth / 2);
			trect.setWidth(rectWidth);
			trect.setHeight(rectWidth);

			painter.drawRect(trect);
		}

		// draw editing rect
		Qt::CursorShape shape = cursor().shape();

		if (shape == Qt::SizeAllCursor)
		{
			QRect trect;
			trect.setX(pt1.x() + _endPoint.x() - _startPoint.x());
			trect.setY(pt1.y() + _endPoint.y() - _startPoint.y());
			trect.setWidth(refSize2 * 2);
			trect.setHeight(refSize2 * 2);

			painter.drawRect(trect);
		}
	}
}

void VideoView::drawTextInfo(QPainter &painter)
{
	QFont font("Times", 18);
	font.setBold(true);
	QFontMetrics fm(font);
	QString textString = QString("Frame:%1").arg(_frameIndex);
	int textWidthInPixels = fm.width(textString);
	int textHeightInPixels = fm.height();
	painter.setFont(font);

	QRect canvas = geometry();
	QPoint pt;
	pt.setX(canvas.width() - textWidthInPixels);
	pt.setY(textHeightInPixels);

	QRect rect(pt.x(), pt.y() - textHeightInPixels + 5, textWidthInPixels, textHeightInPixels);
	painter.setBrush(Qt::black);
	painter.setPen(Qt::black);
	painter.drawRect(rect);


	//painter.drawRect(_zoomTestPos.x() - 30, _zoomTestPos.y() - 30, 60, 60);
	
	painter.setBrush(Qt::red);
	painter.setPen(Qt::red);
	painter.drawText(pt, textString);	
}

void VideoView::mouseDoubleClickEvent(QMouseEvent *event)
{
	if (_status == ViewStatus::VW_STATUS_FRAME_DRAGING)
		return;

	if (!_controller->isPaused())
		return;

	Sequence* sequence = _project->getActiveSequence();

	if (!sequence) return;

	QPoint pt = event->pos();
	cv::Point2d cpt = qPoint2cvPoint(pt);

	std::vector<TrackedObject*>* objects = sequence->getTrackedObjects();

	bool rectSelectedFlag = false;

	TrackedObject* selectedObject = NULL;

	for (int i = 0; i < objects->size(); i++)
	{
		TrackedObject* obj = objects->at(i);

		if (!obj->isVisible())
			continue;

		cv::Rect2d orect = obj->getRect(_frameIndex);
		double osize = orect.area();

		if ((cpt.x <= orect.x + orect.width) &&
			(cpt.x >= orect.x) &&
			(cpt.y <= orect.y + orect.height) &&
			(cpt.y >= orect.y))
		{
			if (selectedObject)
			{
				double ssize = selectedObject->getRect(_frameIndex).area();

				if (osize < ssize)
				{
					selectedObject->deselect();
					selectedObject = obj;
					selectedObject->select();
				}
				else
				{
					obj->deselect();
				}
			}
			else
			{
				selectedObject = obj;
				selectedObject->select();
			}
			
		}
		else
		{
			obj->deselect();
		}
	}

	if (selectedObject)
	{
		rectSelectedFlag = true;

		Shape* shape = selectedObject->getShape(_frameIndex);
		if (ShapeFish* shapeFish = dynamic_cast<ShapeFish*>(shape))
		{
			if (shapeFish->isPointOnHeadIcon(cpt))
				shapeFish->setSelectStatus(SFS_HEAD);
			else if (shapeFish->isPointOnMassIcon(cpt))
				shapeFish->setSelectStatus(SFS_MASS);
			else
				shapeFish->setSelectStatus(SFS_NONE);
		}
	}

	if (rectSelectedFlag)
	{
		_status = VW_STATUS_EDITING;
		clearRects();
		emit objectSelected();
	}
	else
	{
		_status = VW_STATUS_DISPLAYING;
		emit objectUnSelected();
	}
	
	update();
}

void VideoView::reset()
{
	if (_imageData)
	{
		free(_imageData);
		_imageData = 0;
	}
}



void VideoView::drawFishHeadCenter(QPainter& painter, ShapeFish* shape)
{
    // Draw Cross
	cv::Point2d hc = shape->getHeadCenter();

	QPoint headCenter = cvPoint2QPoint(hc);

	cv::Rect2d rect = shape->getRect();

	float refSize = vmin(rect.width, rect.height) * FISH_ICON_RATIO;


    painter.drawLine(QPoint(headCenter.x() - refSize, headCenter.y()), QPoint(headCenter.x() + refSize, headCenter.y()));
    painter.drawLine(QPoint(headCenter.x(), headCenter.y() - refSize), QPoint(headCenter.x(), headCenter.y()+ refSize));

    // Draw Diamond
    QPolygon polygon;
	float refSize2 = refSize * 2;

    polygon.push_back(QPoint(headCenter.x()- refSize2,headCenter.y()));
    polygon.push_back(QPoint(headCenter.x(), headCenter.y() - refSize2));
    polygon.push_back(QPoint(headCenter.x() + refSize2, headCenter.y()));
    polygon.push_back(QPoint(headCenter.x(), headCenter.y()+ refSize2));

    painter.drawPolygon(polygon);
}

void VideoView::drawFishMassCenter(QPainter& painter, ShapeFish* shape)
{
    // Draw Cross
	cv::Point2d mc = shape->getMassCenter();
	QPoint massCenter = cvPoint2QPoint(mc);

	cv::Rect2d rect = shape->getRect();

	float refSize = vmin(rect.width, rect.height) * FISH_ICON_RATIO;

    painter.drawLine(QPoint(massCenter.x() - refSize, massCenter.y()), QPoint(massCenter.x() + refSize, massCenter.y()));
    painter.drawLine(QPoint(massCenter.x(), massCenter.y() - refSize), QPoint(massCenter.x(), massCenter.y()+ refSize));

    // Draw Square
    QPolygon polygon;
	float refSize2 = refSize * 2;

    polygon.push_back(QPoint(massCenter.x()- refSize2,massCenter.y()- refSize2));
    polygon.push_back(QPoint(massCenter.x()+ refSize2,massCenter.y()- refSize2));
    polygon.push_back(QPoint(massCenter.x()+ refSize2,massCenter.y()+ refSize2));
    polygon.push_back(QPoint(massCenter.x()- refSize2,massCenter.y()+ refSize2));

    painter.drawPolygon(polygon);
}

void VideoView::drawTrackedObjectFish(QPainter &painter, TrackedObject *tobj)
{
    ShapeFish* shape = (ShapeFish*)tobj->getShape(_frameIndex);

    cv::Rect2d crect = shape->getRect();

    if (crect.x == 0.0 && crect.y == 0.0 && crect.width == 0.0 && crect.height == 0.0)
        return;

    int classIndex = tobj->getClassIndex();
    std::vector<Class*>* classes = _project->getClasses();

    QString objectClassName = QString("Object");

    for (int j = 0; j < classes->size(); j++)
    {
        Class* cls = classes->at(j);

        if (cls->getId() == classIndex)
        {
            objectClassName = cls->getName().c_str();
            break;
        }
    }

    //bool noSelectedObjectToDraw = false;
    QPen pen;
    pen.setStyle(Qt::SolidLine);
    pen.setWidth(3);
    pen.setColor(QColor(0, 0, 255, 127));
    painter.setPen(pen);

    QRect rect = cvRect2QRect(crect);

    QFont font("Times", 12);
    font.setBold(true);
    QFontMetrics fm(font);
    QString textString = QString("%1:%2").arg(objectClassName).arg(tobj->getObjectId());

    int textWidthInPixels = fm.width(textString);
    int textHeightInPixels = fm.height();
    painter.setFont(font);

    QRect textRect;
    textRect.setX(rect.x());
    textRect.setY(rect.y() - textHeightInPixels - 10 );
    textRect.setHeight(textHeightInPixels + 10 );
    textRect.setWidth(textWidthInPixels + 10 );

    painter.setBrush(Qt::SolidPattern);
    painter.setPen(Qt::NoPen);
    painter.setBrush(QColor(0, 0, 255, 127));
    painter.drawRect(textRect);

    painter.setPen(QColor(255, 255, 0, 255));
    painter.drawText(textRect.x()+5, rect.y() - 5, textString);

    painter.setBrush(Qt::NoBrush);
    painter.setPen(pen);
    painter.drawRect(rect);

    drawFishHeadCenter(painter, shape);
    drawFishMassCenter(painter,shape);

    if (tobj->isSelected())
    {
        drawSelectedObjectFish(painter, shape);
    }
}

void VideoView::drawTrackedObjectRect(QPainter &painter, TrackedObject *tobj)
{
    cv::Rect2d crect = tobj->getRect(_frameIndex);

    if (crect.x == 0.0 && crect.y == 0.0 && crect.width == 0.0 && crect.height == 0.0)
        //continue;
        return;

    int classIndex = tobj->getClassIndex();
    std::vector<Class*>* classes = _project->getClasses();

    QString objectClassName = QString("Object");

    for (int j = 0; j < classes->size(); j++)
    {
        Class* cls = classes->at(j);

        if (cls->getId() == classIndex)
        {
            objectClassName = cls->getName().c_str();
            break;
        }
    }

    //noSelectedObjectToDraw = false;

    QRect rect = cvRect2QRect(crect);

    QPen pen;
    pen.setStyle(Qt::SolidLine);
    pen.setWidth(3);
    pen.setColor(QColor(0, 0, 255, 127));
    painter.setPen(pen);

    QFont font("Times", 12);
    font.setBold(true);
    QFontMetrics fm(font);
    QString textString = QString("%1:%2").arg(objectClassName).arg(tobj->getObjectId());

    int textWidthInPixels = fm.width(textString);
    int textHeightInPixels = fm.height();
    painter.setFont(font);

    QRect textRect;
    textRect.setX(rect.x());
    textRect.setY(rect.y() - textHeightInPixels - 10 );
    textRect.setHeight(textHeightInPixels + 10 );
    textRect.setWidth(textWidthInPixels + 10 );

    painter.setBrush(Qt::SolidPattern);
    painter.setPen(Qt::NoPen);
    painter.setBrush(QColor(0, 0, 255, 127));
    painter.drawRect(textRect);

    painter.setPen(QColor(255, 255, 0, 255));
    painter.drawText(textRect.x()+5, rect.y() - 5, textString);

    painter.setBrush(Qt::NoBrush);
    painter.setPen(pen);
    painter.drawRect(rect);

    if (tobj->isSelected())
    {
        drawSelectedObjectRect(painter, rect);
    }
}

void VideoView::zoomIn()
{
	QPoint mousePos = mapFromGlobal(QCursor::pos());

	QRect imageRect = getImageQRect();

	Sequence* sequence = _project->getActiveSequence();

	int imageWidth = sequence->getVideoWidth();
	int imageHeight = sequence->getVideoHeight();

	QPointF relativePos = QPointF( (mousePos.x() - imageRect.left()) * 1.0 / imageRect.width(),
		(mousePos.y() - imageRect.top()) * 1.0 / imageRect.height());

	//QPoint imagePos = QPoint(imageWidth * mousePos.x() * 1.0 / imageRect.width(),
	//	imageHeight * mousePos.y() * 1.0 / imageRect.height());

	if (_zoomScale < MAX_ZOOM_SCALE)
		_zoomScale = _zoomScale * 2.0;

	_zoomOffset = QPoint(0, 0);

	QRect newImageRect = getImageQRect();

	QPoint newImagePos = QPoint(newImageRect.x() + newImageRect.width() * relativePos.x(),
		newImageRect.y() + newImageRect.height() * relativePos.y());

	_zoomOffset = QPoint(mousePos.x() - newImagePos.x(), mousePos.y() - newImagePos.y());

	_rects.clear();

	update();
}

void VideoView::zoomFit()
{
	_zoomScale = 1.0;
	_zoomOffset.setX(0);
	_zoomOffset.setY(0);

	_rects.clear();

	update();
}

void VideoView::zoomOut()
{
	QPoint mousePos = mapFromGlobal(QCursor::pos());

	_zoomTestPos = mousePos;

	QRect imageRect = getImageQRect();

	Sequence* sequence = _project->getActiveSequence();

	int imageWidth = sequence->getVideoWidth();
	int imageHeight = sequence->getVideoHeight();

	QPointF relativePos = QPointF((mousePos.x() - imageRect.left()) * 1.0 / imageRect.width(),
		(mousePos.y() - imageRect.top()) * 1.0 / imageRect.height());

	if (_zoomScale > MIN_ZOOM_SCALE)
		_zoomScale = _zoomScale * 0.5;

	_zoomOffset = QPoint(0, 0);

	QRect newImageRect = getImageQRect();

	QPoint newImagePos = QPoint(newImageRect.x() + newImageRect.width() * relativePos.x(),
		newImageRect.y() + newImageRect.height() * relativePos.y());

	_zoomOffset = QPoint(mousePos.x() - newImagePos.x(), mousePos.y() - newImagePos.y());

	_rects.clear();

	update();
}

QRect VideoView::getImageQRect()
{
	Sequence* sequence = _project->getActiveSequence();

	int canvasWidth = geometry().width();
	int canvasHeight = geometry().height();

	int imageWidth = sequence->getVideoWidth();
	int imageHeight = sequence->getVideoHeight();

	float imageScale = imageWidth * 1.0 / imageHeight;
	float canvasScale = canvasWidth * 1.0 / canvasHeight;

	QRect targetRect;

	if (canvasScale / imageScale > 1.0)
	{
		targetRect.setX((canvasWidth - canvasHeight * imageScale) / 2.0);
		targetRect.setY(0);
		targetRect.setWidth(canvasHeight * imageScale);
		targetRect.setHeight(canvasHeight);
	}
	else
	{
		targetRect.setX(0);
		targetRect.setY((canvasHeight - canvasWidth / imageScale) / 2.0);
		targetRect.setWidth(canvasWidth);
		targetRect.setHeight(canvasWidth / imageScale);
	}

	_zoomAutoScale = targetRect.width() * 1.0 / imageWidth;

	float totalScale = _zoomAutoScale * _zoomScale;

	int twidth = imageWidth * totalScale;
	int theight = imageHeight * totalScale;

	int left = targetRect.left() + (targetRect.width() - twidth) / 2.0;
	int top = targetRect.top() + (targetRect.height() - theight) / 2.0;

	left += _zoomOffset.x();
	top += _zoomOffset.y();

	if (_status == ViewStatus::VW_STATUS_FRAME_DRAGING)
	{
		left += _endPoint.x() - _startPoint.x();
		top += _endPoint.y() - _startPoint.y();
	}

	return QRect(left, top, twidth, theight);
}

void VideoView::onKeyEscape()
{
	_mainWindow->setCentralWidget(this);
	_mainWindow->zoomFit();
	_mainWindow->setFocusPolicy(Qt::StrongFocus);
}

void VideoView::onKeySpace()
{
	if (ViewStatus::VW_STATUS_DISPLAYING == _status)
	{
		((MainWindow*)_mainWindow)->playOrPauseVideo();
	}
	else
	{
		((MainWindow*)_mainWindow)->nextFrame();
	}
}

void VideoView::wheelEvent(QWheelEvent* event)
{
	if (event->angleDelta().y() > 5)
	{
		zoomIn();
	}
	else if (event->angleDelta().y() < -5)
	{
		zoomOut();
	}
}

void VideoView::keyPressEvent(QKeyEvent* event)
{
	if (event->key() == Qt::Key_A)
		_mainWindow->playOrPauseVideo();
	else if (event->key() == Qt::Key_S)
		_mainWindow->nextFrame();
	else if (event->key() == Qt::Key_D)
		_mainWindow->prevFrame();
	else if (event->key() == Qt::Key_F)
		_mainWindow->zoomFit();
	else if (event->key() == Qt::Key_Z)
		_mainWindow->rects2Objects();
	else if (event->key() == Qt::Key_X)
		_mainWindow->deleteObject();
	else if (event->key() == Qt::Key_C)
		_mainWindow->clearRects();
	else if (event->key() == Qt::Key_T)
		_mainWindow->startTrack();
	else if (event->key() == Qt::Key_Escape)
		onKeyEscape();
	else if (event->key() == Qt::Key_Space)
		_mainWindow->nextFrame();
	else if (event->key() == Qt::Key_PageUp)
		_mainWindow->zoomIn();
	else if (event->key() == Qt::Key_PageDown)
		_mainWindow->zoomOut();
	else if (event->key() == Qt::Key_Delete)
		_mainWindow->deleteObject();
}

void VideoView::pause()
{
	_timer->stop();
}

void VideoView::resume()
{
	_timer->start();
}

void VideoView::rects2objects()
{
	for (int i = 0; i < _rects.size(); i++)
	{
		QRect rect = _rects.at(i);
		qRect2cvRect(rect);
	}
}